package com.danco.training.zaneuskaya.controller;


import java.io.IOException;
import java.util.Date;
import java.util.List;

import com.danco.training.zaneuskaya.api.BookController;
import com.danco.training.zaneuskaya.api.BookService;
import com.danco.training.zaneuskaya.api.OrderController;
import com.danco.training.zaneuskaya.api.OrderService;
import com.danco.training.zaneuskaya.communication.MessageAnalyzer;
import com.danco.training.zaneuskaya.dependency.DependencyConfiguration;
import com.danco.training.zaneuskaya.domain.Book;
import com.danco.training.zaneuskaya.domain.Order;
import com.danco.training.zaneuskaya.view.IOUtil;





public class OrderControllerImpl implements OrderController{
	

	private static final String UPDATE_ENTITY = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;updateEntity";
	private static final String READ_ENTITY_LIST_FROM_FILE = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;readEntityList";
	private static final String SAVE_ENTITY_LIST_TO_FILE = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;saveEntityListToFile";
	private static final String CREATE_ORDER_COPY = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;createOrderCopy";
	private static final String EXECUTE_ORDER_BY_ID = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;executeOrderById";
	private static final String REMOVE_BOOK_FROM_ORDER = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;removeBookFromOrder";
	private static final String REMOVE_ENTITY_BY_ID = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;removeEntityById";
	private static final String GET_BY_ID = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;getById";
	private static final String ADD_BOOK_TO_ORDER = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;addBookToOrder";
	private static final String GET_BY_BOOK_ID = "com.danco.training.zaneuskaya.service.impl.BookServiceImpl;getById";
	private static final String ADD_ENTITY = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;addEntity";
	private static final String GET_EXECUTED_ORDERS_SORTED_BY_PRICE = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;getExecutedOrdersSortedByPrice";
	private static final String GET_EXECUTED_ORDERS_SORTED_BY_ORDER_DATE = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;getExecutedOrdersSortedByOrderDate";
	private static final String GET_NOT_EXECUTED_ORDERS = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;getNotExecutedOrders";
	private static final String GET_EXECUTED_ORDERS = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;getExecutedOrders";
	private static final String GET_ORDERS_SORTED_BY_ORDER_DATE = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;getOrdersSortedByOrderDate";
	private static final String GET_LIST = "com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;getList";
	
	
	
	private static final String READ_ORDER_LIST_FROM_FILE_MESSAGE = "Enter directory and file name to read order list ";
	private static final String SAVED_BY_DEFAULT_IN = "Saved by default in ";
	private static final String FILE_TO_SAVE_ORDER_LIST = "d:\\file1.csv";
	private static final String SAVE_ORDER_LIST_TO_FILE_MESSAGE = "Enter directory and file name for saving";
	private static final String COPY_ORDER_MESSAGE = "Enter order Id to copy";
	private static final String EXECUTE_ORDER_MESSAGE = "Enter order id to execute";
	
	private static final String ENTER_BOOK_ID_TO_DELETE = "Enter book id to delete";
	private static final String DELETE_BOOK_FROM_ORDER_MESSAGE = "Enter book id to delete from order";
	private static final String ADD_BOOK_TO_ORDER_MESSAGE = "Enter order id to add book";
	private static final String DELETE_ORDER_MESSAGE = "Enter order Id";
	private static final String CHANGE_ORDER_STATE_TRUE = "y";
	private static final String CHANGE_ORDER_STATE = "Change order state : y/n";
	private static final String UPDATE_ORDER_MESSAGE = "Enter order Id for modifying";
	private static final String ORDER_NOT_EXISTED_MESSAGE = "Order not existed";
	private static final String PRINT_ORDER_INFO_MESSAGE = "Enter order Id:";
	private static final String ENTER_BOOK_ID_TO_ADD_IN_ORDER = "Enter book Id to add:";
	private static final String CREATE_ORDER_MESSAGE = "Order creation";
	private static final String PRINT_EXECUTED_ORDER_LIST_SORTED_BY_PRICE = "Executed Orders in OrderStorage sorted by price ";
	private static final String PRINT_EXECUTED_ORDER_LIST_SORTED_BY_ORDER_DATE_MESSAGE = "Executed Orders in OrderStorage sorted by execution date ";
	private static final String ENTER_DATE_TO_FOR_ORDER_SORTING = "Enter date day to";
	private static final String ENTER_DATE_FROM_FOR_ORDER_SORTING = "Enter date from ";
	private static final String PRINT_NOT_EXECUTED_ORDERS_MESSAGE = "Not Executed Orders in OrderStorage ";
	private static final String PRINT_EXECUTED_ORDERS_MESSAGE = "Executed Orders in OrderStorage ";
	private static final String PRINT_ORDER_LIST_SORTED_BY_ORDER_DATE_MESSAGE = "Orders in OrderStorage sorted by execution date";
	private static final String PRINT_ORDER_LIST_MESSAGE = "Orders in OrderStorage";
	
	
	private BookController bookController = (BookController) DependencyConfiguration.getInstanceByClassName(BookController.class);

	@SuppressWarnings("unchecked")
	public void printOrderList() {
		IOUtil.write(PRINT_ORDER_LIST_MESSAGE);
		List<Order> orders;
		try {
		
			orders = (List<Order>) MessageAnalyzer.executeMethod(GET_LIST, null);
			for(Order order:orders){
				IOUtil.write(orderInfo(order.getId()));
				}
		} catch (IOException e) {
			IOUtil.write(e.getMessage()+ "Wrong Input");
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}
		
		
	}

	public void printOrderListSortedByOrderDate()  {
		IOUtil.write(PRINT_ORDER_LIST_SORTED_BY_ORDER_DATE_MESSAGE);
	
		List<Order> sortedOrders = null;
		try {
			
			sortedOrders = (List<Order>)MessageAnalyzer.executeMethod(GET_ORDERS_SORTED_BY_ORDER_DATE, new Object []{});
			for(Order order:sortedOrders){
				IOUtil.write(orderInfo(order.getId()));
				}
			
		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}
		
	}
	
	public void printOrderListSortedByPrice(){
		List<Order> sortedOrders = null;
		try {
			
			sortedOrders = (List<Order>)MessageAnalyzer.executeMethod("com.danco.training.zaneuskaya.service.impl.OrderServiceImpl;getOrdersSortedByTotalPrice", new Object []{});
			for(Order order:sortedOrders){
				IOUtil.write(orderInfo(order.getId()));
				}
			
		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}
	}

	public void printExecutedOrders() {
		IOUtil.write(PRINT_EXECUTED_ORDERS_MESSAGE);
		
		List<Order> sortedOrders = null;
		try {
			
			sortedOrders = (List<Order>)MessageAnalyzer.executeMethod(GET_EXECUTED_ORDERS, new Object []{});
			for(Order order:sortedOrders){
				IOUtil.write(orderInfo(order.getId()));
				}
			
		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}
		

	}

	public void printNotExecutedOrders() {
		IOUtil.write(PRINT_NOT_EXECUTED_ORDERS_MESSAGE);
		
		List<Order> sortedOrders = null;
		try {
			
			sortedOrders = (List<Order>) MessageAnalyzer.executeMethod(GET_NOT_EXECUTED_ORDERS, new Object []{});
			for(Order order:sortedOrders){
				IOUtil.write(orderInfo(order.getId()));
				}
		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}
		
		
	}

	public void printExecutedOrderListSortedByOrderDate() {
		IOUtil.write(ENTER_DATE_FROM_FOR_ORDER_SORTING);
		try {
		Date d1 = IOUtil.readDate();
		IOUtil.write(ENTER_DATE_TO_FOR_ORDER_SORTING);
		
		Date d2 = IOUtil.readDate();
		IOUtil.write(PRINT_EXECUTED_ORDER_LIST_SORTED_BY_ORDER_DATE_MESSAGE);
		
		List<Order> sortedOrders = null;
		
		
			sortedOrders = (List<Order>) MessageAnalyzer.executeMethod(GET_EXECUTED_ORDERS_SORTED_BY_ORDER_DATE, new Object [] {d1, d2});
			for(Order order:sortedOrders){
				IOUtil.write(orderInfo(order.getId()));
				}
		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}
		
		

	}

	public void printExecutedOrderListSortedByPrice()  {
        IOUtil.write(ENTER_DATE_FROM_FOR_ORDER_SORTING);
		
		Date d1 = IOUtil.readDate();
		IOUtil.write(ENTER_DATE_TO_FOR_ORDER_SORTING);
		
		Date d2 = IOUtil.readDate();
		IOUtil.write(PRINT_EXECUTED_ORDER_LIST_SORTED_BY_PRICE);
		
		List<Order> sortedOrders = null;
		try {
			
			sortedOrders = (List<Order>) MessageAnalyzer.executeMethod(GET_EXECUTED_ORDERS_SORTED_BY_PRICE, new Object [] {d1, d2});
			for(Order order:sortedOrders){
				IOUtil.write(orderInfo(order.getId()));
				}
		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}
		
	}

	public void createOrder(){
		IOUtil.write(CREATE_ORDER_MESSAGE);
		
		try {
			
			
			Order order = new Order();
			MessageAnalyzer.executeMethod(ADD_ENTITY,new Object []{ order});
			IOUtil.write(ENTER_BOOK_ID_TO_ADD_IN_ORDER);
			bookController.printBookList();
			int bookId = IOUtil.readInt();
			Book book = (Book) MessageAnalyzer.executeMethod(GET_BY_BOOK_ID, new Object []{bookId});
			MessageAnalyzer.executeMethod(ADD_BOOK_TO_ORDER, new Object []{order,book});
			IOUtil.write(orderInfo(order.getId()));
		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			
			IOUtil.write(e.getMessage());
		}
		
	}
	
	

	public void printOrderInfo() {
		IOUtil.write(PRINT_ORDER_INFO_MESSAGE);
		int id = IOUtil.readInt();
		Order order = null;
		
			try {
				order = (Order) MessageAnalyzer.executeMethod(GET_BY_ID, new Object []{id});
			
	 
		while (order == null){
			IOUtil.write(ORDER_NOT_EXISTED_MESSAGE);
			IOUtil.write(PRINT_ORDER_INFO_MESSAGE);
			id = IOUtil.readInt();
		}
		IOUtil.write(orderInfo(order.getId()));
			} catch (ClassNotFoundException e) {
				IOUtil.write(e.getMessage());
			} catch (IOException e) {
				IOUtil.write(e.getMessage());
			}
	}
	
	
	public String orderInfo(Integer id){
		StringBuffer str = new StringBuffer(id + "  ");
		Order order = null;
		try {
			order = (Order) MessageAnalyzer.executeMethod(GET_BY_ID, new Object []{id});
		
		str.append(" Books:");
		for (Book book : order.getBooks()) {
			str.append(book.getId());
			str.append(" ");

		}
		str.append(" Executed: ");
		str.append(order.isExecuted()+ "  ");
		str.append(order.getTotalPrice());
		
		}
		catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}
		return str.toString();
	}

	public void updateOrder(){
		
		Order order = null;
		
		while (order == null){
			
			IOUtil.write(UPDATE_ORDER_MESSAGE);
			int id = IOUtil.readInt();
			try {
				order = (Order) MessageAnalyzer.executeMethod(GET_BY_ID,new Object []{ id});
				IOUtil.write(CHANGE_ORDER_STATE);
				if (!IOUtil.read().equals(CHANGE_ORDER_STATE_TRUE) ){
					order.setExecuted(!order.isExecuted());
				}
				MessageAnalyzer.executeMethod(UPDATE_ENTITY,new Object []{ order});
				IOUtil.write(orderInfo(order.getId()));
				
			} catch (IOException e) {
				IOUtil.write(e.getMessage());
			} catch (ClassNotFoundException e) {
				IOUtil.write(e.getMessage());
			}
		}
	
		

	}

	public void deleteOrder() {
		Order order = null;
		int id = 0;
		while (order == null){
			IOUtil.write(DELETE_ORDER_MESSAGE);
			id = IOUtil.readInt();
			try {
				order = (Order) MessageAnalyzer.executeMethod(GET_BY_ID, new Object []{id});
				MessageAnalyzer.executeMethod(REMOVE_ENTITY_BY_ID, new Object []{id});
		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}
		}
		
	}

	public void addBookToOrder() {
		Order order = null;
		Book book = null;
		int id = 0;
		while (order == null){
			
			IOUtil.write(ADD_BOOK_TO_ORDER_MESSAGE);
			id = IOUtil.readInt();
			try {
				order = (Order) MessageAnalyzer.executeMethod(GET_BY_ID,new Object []{ id});
			} catch (IOException e) {
				IOUtil.write(e.getMessage());
			} catch (ClassNotFoundException e) {
				IOUtil.write(e.getMessage());
			}
		}
		
		
		
		bookController.printBookList();
		
		while (book == null){
		
			IOUtil.write(ENTER_BOOK_ID_TO_ADD_IN_ORDER);
			
			int bookId = IOUtil.readInt();
			try {
				book = (Book)MessageAnalyzer.executeMethod(GET_BY_BOOK_ID, new Object []{bookId});
		
				MessageAnalyzer.executeMethod(ADD_BOOK_TO_ORDER, new Object[] {order, book});
		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}
		}
		

	}

	public void deleteBookFromOrder() {
		Order order = null;
		while (order == null){
			IOUtil.write(DELETE_BOOK_FROM_ORDER_MESSAGE);
			int id = IOUtil.readInt();
			Book book = null;
			try {
				
				order = (Order) MessageAnalyzer.executeMethod(GET_BY_ID, new Object []{id});
				while (book == null){
					
					IOUtil.write(ENTER_BOOK_ID_TO_DELETE);
					int bookId = IOUtil.readInt();
					
						book = (Book)MessageAnalyzer.executeMethod(GET_BY_BOOK_ID, new Object []{bookId});
				}
				MessageAnalyzer.executeMethod(REMOVE_BOOK_FROM_ORDER, new Object[]{ order, book});
			         IOUtil.write(orderInfo(order.getId()));
		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}
		}
		

	}

	public void executeOrder() {
		Order order = null;
		int id = 0;
		while (order == null){
			
			IOUtil.write(EXECUTE_ORDER_MESSAGE);
			id = IOUtil.readInt();
			try {
				order = (Order) MessageAnalyzer.executeMethod(GET_BY_ID,new Object []{ id});
			
				MessageAnalyzer.executeMethod(EXECUTE_ORDER_BY_ID,new Object []{ id});
		} catch (IOException e) {
			IOUtil.write(e.getMessage());
		} catch (ClassNotFoundException e) {
			IOUtil.write(e.getMessage());
		}
		}
		
	}

	public void copyOrder(){
		Order order = null;
		Order copy = null;
		while (order == null){
			
			IOUtil.write(COPY_ORDER_MESSAGE);
			int id = IOUtil.readInt();
			try {
				order = (Order) MessageAnalyzer.executeMethod(GET_BY_ID, new Object []{id});
				copy = (Order) MessageAnalyzer.executeMethod(CREATE_ORDER_COPY,new Object []{ order});
				IOUtil.write(orderInfo(copy.getId()));
				} catch (IOException e) {
					IOUtil.write(e.getMessage());
				} catch (ClassNotFoundException e) {
					IOUtil.write(e.getMessage());
				}
		}
				
			
		
		
	}

	public void saveOrderListToFile()  {
		 IOUtil.write(SAVE_ORDER_LIST_TO_FILE_MESSAGE);
			String file = IOUtil.read();
			if (file.isEmpty()){
				file = FILE_TO_SAVE_ORDER_LIST;
				IOUtil.write(SAVED_BY_DEFAULT_IN + FILE_TO_SAVE_ORDER_LIST);
				
			}
			try {
				MessageAnalyzer.executeMethod(SAVE_ENTITY_LIST_TO_FILE,new Object []{ file});
			} catch (IOException e) {
				IOUtil.write(e.getMessage());
			} catch (ClassNotFoundException e) {
				IOUtil.write(e.getMessage());
			}
			
				
	}
	
	public void readOrderListFromFile(){
		 IOUtil.write(READ_ORDER_LIST_FROM_FILE_MESSAGE);
			String file = IOUtil.read();
			if (file.isEmpty()){
				file = FILE_TO_SAVE_ORDER_LIST;
					
			}
			List<Order> orders = null;
			try {
				orders = (List<Order>) MessageAnalyzer.executeMethod(READ_ENTITY_LIST_FROM_FILE,new Object []{ file});
			
			for (Order or: orders){
				
				MessageAnalyzer.executeMethod(ADD_ENTITY,new Object []{ or});
			}
				} catch (IOException e) {
					IOUtil.write(e.getMessage());
				} catch (ClassNotFoundException e) {
					IOUtil.write(e.getMessage());
				}
				
			
	}
	

	
}
